﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading;
using UnityEngine;

namespace Frame.Ctrl
{
    public class NodeManager
    {
        private static NodeManager s_singleton = default(NodeManager);
        private static object s_objectLock = new object();
        public static NodeManager Instance
        {
            get
            {
                if (NodeManager.s_singleton == null)
                {
                    object obj;
                    Monitor.Enter(obj = NodeManager.s_objectLock);//加锁防止多线程创建单例
                    try
                    {
                        if (NodeManager.s_singleton == null)
                        {
                            NodeManager.s_singleton = ((default(NodeManager) == null) ? Activator.CreateInstance<NodeManager>() : default(NodeManager));//创建单例的实例
                        }
                    }
                    finally
                    {
                        Monitor.Exit(obj);
                    }
                }
                return NodeManager.s_singleton;
            }
        }

        private List<BaseNode> enterNodes;
        private List<BaseNode> updateNodes;
        private Dictionary<string, List<BaseNode>> excuteDic;
        private Dictionary<string, List<BaseNode>> tryGetValueDic;
        public NodeManager()
        {
            enterNodes = new List<BaseNode>();
            updateNodes = new List<BaseNode>();
            excuteDic = new Dictionary<string, List<BaseNode>>();
            tryGetValueDic = new Dictionary<string, List<BaseNode>>();
        }
        public void RegstorExcute(BaseNode node)
        {
            if (node == null)
                return;
            string[] msgs = node.ListExcute.ToArray();
            for (int i = 0; i < msgs.Length; i++)
            {
                if (!excuteDic.ContainsKey(msgs[i]))
                    excuteDic[msgs[i]] = new List<BaseNode>();
                if (!excuteDic[msgs[i]].Contains(node))
                    excuteDic[msgs[i]].Add(node);
            }
        }
        public void UnRegstorExcute(BaseNode node)
        {
            if (node == null)
                return;
            string[] msgs = node.ListExcute.ToArray();
            for (int i = 0; i < msgs.Length; i++)
            {
                if (!excuteDic.ContainsKey(msgs[i]))
                    continue;
                if (excuteDic[msgs[i]].Contains(node))
                    excuteDic[msgs[i]].Remove(node);
            }
        }

        public void RegstorTryGetValue(BaseNode node)
        {
            if (node == null)
                return;
            string[] msgs = node.ListTryGetValue.ToArray();
            for (int i = 0; i < msgs.Length; i++)
            {
                if (!tryGetValueDic.ContainsKey(msgs[i]))
                    continue;
                if (tryGetValueDic[msgs[i]].Contains(node))
                    tryGetValueDic[msgs[i]].Remove(node);
            }
        }
        public void UnRegstorTryGetValue(BaseNode node)
        {
            if (node == null)
                return;
            string[] msgs = node.ListTryGetValue.ToArray();
            for (int i = 0; i < msgs.Length; i++)
            {
                if (!tryGetValueDic.ContainsKey(msgs[i]))
                    tryGetValueDic[msgs[i]] = new List<BaseNode>();
                if (!tryGetValueDic[msgs[i]].Contains(node))
                    tryGetValueDic[msgs[i]].Add(node);
            }
        }

        public void RegstorEnter(BaseNode node)
        {
            if (node != null && !enterNodes.Contains(node)) enterNodes.Add(node);
        }
        public void UnRegstorEnter(BaseNode node)
        {
            if (node != null && enterNodes.Contains(node)) enterNodes.Remove(node);
        }
        public void RegstorUpdate(BaseNode node)
        {
            if (node != null && !updateNodes.Contains(node)) updateNodes.Add(node);
        }
        public void UnRegstorUpdate(BaseNode node)
        {
            if (node != null && updateNodes.Contains(node)) updateNodes.Remove(node);
        }
        public void Update()
        {
            BaseNode[] nodes = updateNodes.ToArray();
            for (int i = 0; i < nodes.Length; i++)
            {
                nodes[i].Update();
            }
        }

        public void Excute(string msg, object[] data)
        {
            if (excuteDic.ContainsKey(msg))
            {
                BaseNode[] nodes = excuteDic[msg].ToArray();
                for (int i = 0; i < nodes.Length; i++)
                {
                    nodes[i].Excute(msg, data);
                }
            }
        }

        public bool TryGetValue(string msg, string key, out object data)
        {
            if (tryGetValueDic.ContainsKey(msg))
            {
                BaseNode[] nodes = tryGetValueDic[msg].ToArray();
                for (int i = 0; i < nodes.Length; i++)
                {
                    if (nodes[i].TryGetValue(msg, key, out data))
                    {
                        return true;
                    }
                }
            }
            data = null;
            return false;
        }
    }
}
